package com.diorsunion.hedge.bo.datasync;

import com.diorsunion.hedge.bo.db.StockPriceBO;
import com.diorsunion.hedge.bo.net.DataFetcher;
import com.diorsunion.hedge.enums.Period;
import com.diorsunion.hedge.quota.*;
import com.diorsunion.hedge.dal.repository.stock.StockPriceExRepository;
import com.diorsunion.hedge.util.CalendarUtils;
import com.diorsunion.hedge.dal.entity.stock.Stock;
import com.diorsunion.hedge.dal.entity.stock.StockPrice;
import com.diorsunion.hedge.dal.repository.stock.StockPriceRepository;
import com.diorsunion.hedge.dal.repository.stock.StockRepository;
import com.diorsunion.hedge.util.LogUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import javax.annotation.Resource;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * 股票数据同步抽象父类
 * Created by harley-dog<custer7572@163.com> on 2015/12/12.
 */
public abstract class StockDataSync {

    @Resource
    protected StockPriceRepository stockPriceRepository;
    @Resource
    protected StockPriceExRepository stockPriceExRepository;
    @Resource
    protected StockRepository stockRepository;
    @Resource
    DataFetcher dataFetcher;
    @Resource
    StockPriceBO stockPriceBO;

    Set<StockPriceExFilter> exFilter = Sets.newHashSet();

    protected abstract Period getPeriod();

    protected abstract Date getBegin(Date date, Stock stock);

    protected abstract Date getEnd(Date date, Stock stock);

    protected StockDataSync() {
        exFilter.add(new RSIFilter(5, 10, 20));
        exFilter.add(new MACDFilter(12, 26));
        exFilter.add(new KDJFilter(9, 3, 3));
        exFilter.add(new BollFilter(20, 2));
    }

    /**
     * 同步股票价格数据到数据库
     * 数据源：网络
     * 同时还要计算各种量化指标
     *
     * @param date  同步截至的日期(可以认为是endDate)
     * @param stock 要同步的股票 (需要id,code两个字段)
     * @throws Exception
     */
    public void sync(Date date, Stock stock) throws Exception {
        Period period = getPeriod();
        Date begin = getBegin(date, stock);
        Date end = getEnd(date, stock);
        LogUtil.info(LogUtil.task, period + " sync [" + CalendarUtils.formatFull(begin) + " ~ " + CalendarUtils.formatFull(begin) + "] ,stock:" + stock);
        /*先从网上巴拉下来数据*/
        List<StockPrice> stockPriceList = dataFetcher.fetchStockPrice(stock, begin, end, period);
        /*然后再一条条插入到数据库里去*/
        stockPriceList.stream()
                .sorted((x, y) -> x.thedate.compareTo(y.thedate))
                .forEach(stockPrice -> stockPriceBO.insert(stock, stockPrice, getPeriod()));
        syncEx(stock,end);
    }

    //为了计算量化指标，需要的历史数据最多查询条数
    public final static int last_num = 30;
    /**
     * 计算量化指标数据到数据库
     * 数据源：数据库里的stockPrice数据
     * @param stock
     * @param end
     */
    public void syncEx(Stock stock, Date end) {
        Period period = getPeriod();
        //maxDate是指有ex数据的最大日期
        Date begin = stockPriceExRepository.getMaxDate(stock, end, period);
        if (begin == null) {
            begin = stockPriceRepository.getMinDate(stock,period);
        }
        List<StockPrice> stockPrices = stockPriceRepository.findStockPriceWithEx(stock, begin, end, period);
        List<StockPrice> updateExPrices = Lists.newArrayList();
        stockPrices.stream()
                .filter(x -> x.ex.thedate == null)
                .forEach(x -> updateExPrices.add(x));
        List<StockPrice> lastList = stockPriceRepository.findStockPriceWithExNum(stock,begin,last_num,period);
        exFilter.stream().forEach( x-> x.filter(stock,lastList,updateExPrices));
        updateExPrices.stream().forEach( x ->{
            x.ex.id = x.id;
            x.ex.stock = x.stock;
            x.ex.thedate = x.thedate;
            stockPriceExRepository.insert(x.ex,period);
        });
    }

}
